#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
using namespace std;
#if 0
int main()
{
  pid_t pid = fork();
  if(pid == 0)
  {
    while(1)
    {
      cout <<"I am child,my pid:" <<getpid() <<" myppid:" << getppid() << endl;
      sleep(2);
    }
    //bort();//给当前发送6号信号
    //raise(3);
  }
  int status = 0;
  waitpid(pid,&status,0);//0:表示阻塞等待 WNOHANG:表示非阻塞等待
  cout <<"I am father pid:" << getpid() << endl;
  //在status的低16位当中,低7位:是否收到信号(若不是0，则代表信号的编号)
  //第8位：coredump标志位，表示程序在异常退出的时候是否进行了核心转储
  //高8位：退出码 
  printf("exitCode:%d,coredump:%d,exitSignal:%d\n",(status >> 8)&0xff,(status >> 7)&1,status &0x7f);
  return 0;
}
#endif

//统计一秒能将一个变量累加到多大
//int g_val;
//void handle(int signo)
//{
//  cout <<"Receive signal:" << signo<< endl;
//  cout <<"g_val:" << g_val << endl;
//  exit(1);
//}
//int main()
//{
//  signal(14,handle);
//  alarm(1);//设计一个定时器，让OS在1s后给当前进程发送14号信号
//  while(1)
//  {
//    g_val++;
//  }
//  return 0;
//}


//解决僵尸问题:三种方法
/*僵尸进程产生的原因:子进程退出后，父进程没有读取子进程的退出信息，OS还需要维护子进程的pcb(进程的退出信息保存早PCB当中),此时子进程的状态为Z,并且由于僵尸进程是已经结束的进程，所以不能被杀死
*/
//case1:父进程通过waitpid/wait的方式等待子进程退出
//case2:由于子进程在退出的时候会给父进程发送SIGCHLD信号,所以父进程可以自定义该信号的处理动作，
// 在处理动作当中清理子进程的资源
//case3:在Linux下,可以将SIGCHID信号的处理方式设置为忽略:SIG_IGN,这样子进程在退出的时候会自动释放其资源  
//注意:信号的默认处理动作为忽略，和我们自己捕获信号将其处理动作设置为忽略没有区别
//case4:创建爷孙进程
//爷爷进程fork创建一个父亲进程，然后爷爷进程等待该父亲进程退出，父亲进程创建一个孙子进程后立马退出，此时爷爷进程就可以获取该父亲进程的退出结果然后继续往后执行不必关心孙子进程，此时孙子进程由于父亲进程退出，其会变成孤儿进程,由1号进程领养，孙子进程退出后由1号进程负责回收其资源，所以不会造成内存泄漏


void handle(int sig)
{
  printf("recevie signal:%d\n",sig);
  int status = 0;
  int res = 0;
  //waitpid()函数返回值大于0表示已经有子进程结束，等于0表示没有已结束的子进程，小于0表示出现错误
  //标准输出函数是不可重入的
  while((res = waitpid(-1,&status,WNOHANG)) > 0)
  {
      printf("child pid:%d exit....,exitCode:%d,exitSignal:%d,coredump:%d\n",res,\
        (status>>8)&0xff,status&0x7f,(status>>7)&1);
  }
}
int main()
{
  signal(SIGCHLD,handle);
  for(int i = 0;i<5;i++)
  {
    pid_t pid = fork(); 
    if(pid == 0)
    {
      //child
      int count = 2;
      while(count)
      {
        count--;
        printf("I am child ...My pid:%d,ppid:%d\n",getpid(),getppid());
        sleep(1);
      }
      exit(1);
    }
  }
  
  //parent
  while(1)
  {
    printf("father working....\n");
    sleep(2);
  }
  return 0;
}
